package org.papervision3d.cameras
{
	import org.papervision3d.objects.DisplayObject3D;
	import logout.pv.perso.Perso;
	import flash.events.Event;
	import org.papervision3d.core.Number3D;
	import org.papervision3d.core.Matrix3D;
	import caurina.transitions.Tweener;

	public class ThirdPersonCamera extends Camera3D
	{
		
		private namespace fps;
		private namespace normal;
		private namespace tween;
		
		public static const FPS_MODE : String = "fpsMode";
		public static const NORMAL_MODE : String = "normalMode";
		
		private var ns : Namespace = fps
		
		
		public var smoothMovment : Number = 25;
		public var hAngle : Number = -Math.PI/2;
		public var vAngle : Number = Math.PI/6;
		public var distance : Number = 10000;
		
		public var destination : Number3D;
		
		public function set mode( str : String ) : void {
			ns = ( str == NORMAL_MODE ) ? normal : fps;
		}
		
		public function setNormalMode( target : DisplayObject3D, destination : Number3D ) : void {
			this.target = target;
			this.destination = destination;
			ns =  normal;
		}

		public function startTweenMode( target : *, destination : Number3D , time : Number) : void {
			ns = tween;
			
			this.destination = new Number3D( x, y, z );
			Tweener.addTween( targetLookAt, { 	x : target.x,
												y : target.y,
												z : target.z,
												time : time
										});
												
			Tweener.addTween( this.destination, { 	x : destination.x,
												y : destination.y,
												z : destination.z,
												time : time,
												onComplete : onTweenComplete
										});

			
		}
		
		public function ThirdPersonCamera(target:DisplayObject3D=null, zoom:Number=2.0, focus:Number=100.0, initObject:Object=null)
		{
			super(target, zoom, focus, initObject);
			
			targetLookAt = new Number3D( target.x, target.y, target.z );
			//target.addEventListener( Perso.MOVE, onPersoMove );
			
		}
		
		/*  // [internal-use] Transforms world coordinates into camera space.
        public override function transformView():void
        {
			//lookAt( target );
    
            super.transformView();
        } */
		
		
		/**
		 * enterframe en gros
		 * @param targetObject
		 * @param upAxis
		 * 
		 */		
		override public function lookAt( targetObject:DisplayObject3D, upAxis:Number3D=null ):void
		{
			ns::setTarget();
			ns::setPosition();
			fps::_lookAt( );
		}
		
		fps function _lookAt():void {
			var position :Number3D = new Number3D( this.x, this.y, this.z );
			var target : Number3D = targetLookAt;
	
			var zAxis    :Number3D = Number3D.sub( target, position );
			zAxis.normalize();
	
			if( zAxis.modulo > 0.1 )
			{
				var xAxis :Number3D = Number3D.cross( zAxis, UP );
				xAxis.normalize();
	
				var yAxis :Number3D = Number3D.cross( zAxis, xAxis );
				yAxis.normalize();
	
				var look  :Matrix3D = this.transform;
	
				look.n11 = xAxis.x;
				look.n21 = xAxis.y;
				look.n31 = xAxis.z;
	
				look.n12 = -yAxis.x;
				look.n22 = -yAxis.y;
				look.n32 = -yAxis.z;
	
				look.n13 = zAxis.x;
				look.n23 = zAxis.y;
				look.n33 = zAxis.z;
	
				this._transformDirty = false;
				// TODO: Implement scale
			}
			
		}
		
		fps function setTarget( e : Event = null) : void {
			targetLookAt.x += ( target.x - targetLookAt.x ) / smoothMovment;
			targetLookAt.y += ( target.y - targetLookAt.y ) / smoothMovment;
			targetLookAt.z += ( target.z - targetLookAt.z ) / smoothMovment;
		}
		
		fps function setPosition( e : Event = null) : void {
			
			var rx : Number = Math.cos( vAngle ) * distance * Math.cos( hAngle ) + target.x;
			var rz : Number = Math.cos( vAngle ) * distance * Math.sin( hAngle ) + target.z;
			var ry : Number = distance * Math.sin( vAngle ) + target.y;
			
			x += ( rx -x ) / smoothMovment;
			z += ( rz -z ) / smoothMovment;
			y += ( ry -y ) / smoothMovment;
		}
		
		normal function setTarget( e : Event = null) : void {
			targetLookAt.x += ( target.x - targetLookAt.x ) / smoothMovment;
			targetLookAt.y += ( target.y - targetLookAt.y ) / smoothMovment;
			targetLookAt.z += ( target.z - targetLookAt.z ) / smoothMovment;
		}

		normal function setPosition(e : Event = null ) : void {
			x += ( destination.x -x ) / smoothMovment;
			z += ( destination.z -z ) / smoothMovment;
			y += ( destination.y -y ) / smoothMovment;
		}
		
		tween function setTarget( e : Event = null) : void {
		}
		
		tween function setPosition( e : Event = null) : void {
			x = destination.x;
			y = destination.y;
			z = destination.z;
		}
		
		public function onTweenComplete( ) : void {
			dispatchEvent( new Event( Event.COMPLETE ) );
		}
		
		
		private var targetLookAt : Number3D;
		
		
	}
}